package com.aponteitor.desktop.util;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.Window;
import java.text.ParseException;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.JTextComponent;
import javax.swing.text.MaskFormatter;

import com.aponteitor.desktop.event.HideMessageHandler;
import com.aponteitor.desktop.event.SelectTextHandler;
import com.aponteitor.desktop.event.ShowMessageHandler;
import com.aponteitor.desktop.event.TransferFocusHandler;
import com.aponteitor.desktop.ui.HasTitle;

/**
 * @author wellsantos@wellsantos.com
 */
public class WindowUtil {

    public static <T extends JPanel & HasTitle> void setupSingleton(JFrame frame, T panel){
        setupWindow(frame);
        
        frame.setTitle(panel.getTitle());
        frame.setBounds(panel.getBounds());
        
        if (panel.isPreferredSizeSet()){
            frame.setPreferredSize(panel.getPreferredSize());
        }
        
        Container contentPane = frame.getContentPane();
        
        if (!(contentPane.getLayout() instanceof BorderLayout)){
            contentPane.setLayout(new BorderLayout());
        }
        
        contentPane.add(panel, BorderLayout.CENTER);
    }
    
    public static void setLocationCenter(Window window){
        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension size = window.getSize();
        Dimension screen = tk.getScreenSize();
        Insets insets = tk.getScreenInsets(window.getGraphicsConfiguration());
        int width = screen.width - insets.left - insets.right;
        int height = screen.height - insets.top - insets.bottom;
        window.setLocation(width/2 - (int)size.getWidth()/2, height/2 - (int)size.getHeight()/2);
    }
    
    public static void setupWindow(Window component){
        component.addWindowListener(ShowMessageHandler.get());
        component.setIconImage(ImageConstants.getImage("apontador.png"));
    }
    
    public static void setupTextField(JTextComponent component){
        component.setFont(FontConstants.COURIER_NEW_12);
        component.addFocusListener(SelectTextHandler.get());
        component.addKeyListener(HideMessageHandler.get());
        component.addMouseListener(HideMessageHandler.get());        
    }

    public static void setupTextArea(JTextArea component){
        component.setFont(FontConstants.COURIER_NEW_12);
        component.addKeyListener(HideMessageHandler.get());
        component.addMouseListener(HideMessageHandler.get());
        component.addKeyListener(TransferFocusHandler.get());        
    }

    public static void setupDateField(JFormattedTextField component) {
        try {            
            setupTextField(component);
            component.setFormatterFactory(new DefaultFormatterFactory(new MaskFormatter("##/##/####")));
            component.setFocusLostBehavior(JFormattedTextField.COMMIT);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    
    public static void setupTimeField(JFormattedTextField component){
        try {
            setupTextField(component);
            component.setFormatterFactory(new DefaultFormatterFactory(new MaskFormatter("##:##")));
            component.setFocusLostBehavior(JFormattedTextField.COMMIT);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    
    public static void setupButton(AbstractButton component){        
        component.addActionListener(HideMessageHandler.get());
    }

    public static void setupComboBox(JComboBox component) {
        component.addActionListener(HideMessageHandler.get());
    }
    
    public static ButtonGroup setupButtonGroup(AbstractButton... buttons){
        ButtonGroup buttonGroup = new ButtonGroup();
        for (AbstractButton btn : buttons){
            buttonGroup.add(btn);
            btn.getModel().setGroup(buttonGroup);
        }
        return buttonGroup;
    }
    
    public static Component findComponent(String name, Container parent){
        if (parent != null && name != null){
            for (int i=0, len=parent.getComponentCount(); i<len; i++){
                Component item = parent.getComponent(i);
                if (name.equals(item.getName())){
                    return item;
                }
                if (item instanceof Container){
                    item = findComponent(name, (Container)item);
                    if (item != null){
                        return item;
                    }
                }
            }
        }
        return null;
    }
    
    public static <T> T findComponent(Class<T> type, Container parent){
        if (parent != null && type != null){
            for (int i=0, len=parent.getComponentCount(); i<len; i++){
                Component item = parent.getComponent(i);
                if (type.isAssignableFrom(item.getClass())){
                    return type.cast(item);
                }
                if (item instanceof Container){
                    T item2 = findComponent(type, (Container)item);
                    if (item2 != null){
                        return item2;
                    }
                }
            }
        }
        return null;
    }
    
    public static void showWindow(Window window){
        if (window != null){
            window.setVisible(true);
            if (window instanceof Frame){
                ((Frame)window).setState(Frame.NORMAL);
            }
        }
    }
    
    public static void showWindow(Component component){
        showWindow(getWindow(component));
    }
    
    public static Window getWindow(Component component){
        while (component != null
                && !(component instanceof Window)){
            component = component.getParent();
        }
        return (Window) component;
    }

    public static Frame getFrame(Component component){
        while (component != null
                && !(component instanceof Frame)){
            component = component.getParent();
        }
        return (Frame) component;
    }

    public static Dialog getDialog(Component component){
        while (component != null
                && !(component instanceof Dialog)){
            component = component.getParent();
        }
        return (Dialog) component;
    }

    public static void setEnable(Component target, boolean enable){
        if (target != null){
            target.setEnabled(enable);
            if (target instanceof Container){
                Container container = (Container) target;
                for (int i=container.getComponentCount(); i>0;){
                    setEnable(container.getComponent(--i), enable);
                }
            }
        }
    }
}
